#!/bin/bash
# *************************************
# * 功能: Shell脚本初始化Rocky环境网卡环境
# * 作者: 王树森
# * 联系: wangshusen@sswang.com
# * 版本: 2025-02-20
# *************************************
set -e

# 设定环境变量
rule_file='/etc/udev/rules.d/70.persistent-net.rules'
net_dir='/etc/NetworkManager/system-connections'

# 检查命令是否可用
check_command() {
    local cmd=$1
    if ! command -v "$cmd" &> /dev/null; then
        echo "$cmd 命令未找到，请确保相关软件已安装并运行。"
        exit 1
    fi
}

# 清理无效的连接信息
clean_net_device_msg(){
    # 获取无效的连接
    error_devi=$(nmcli connection  | awk '/--/{print $1}')
    
    # 移除无效连接
    if [ -n "$error_devi" ]; then
        nmcli connection delete $error_devi
    fi
}

# 提取新连接的 UUID 和设备名
extract_connection_info() {
    if [ -n "$new_devi" ]; then
        nmcli device up $new_devi
    fi
    
    new_uuid=$(nmcli connection | awk "/$new_devi/{print \$(NF-2)}")
    if [ -z "$new_uuid" ]; then
        echo "未找到包含 'ens' 的连接信息。"
        exit 1
    fi
}

# 修改连接名称
modify_connection_name() {
    nmcli connection modify "$new_uuid" connection.id "$new_devi"
    if [ $? -ne 0 ]; then
        echo "修改连接名称失败。"
        exit 1
    fi
}

# 提取 MAC 地址
extract_mac_address() {
    mac_num=$(ip a show "$new_devi" | awk '/ether/{print $2}')
    if [ -z "$mac_num" ]; then
        echo "未找到 $new_devi 的 MAC 地址。"
        exit 1
    fi
}

# 计算新的 eth 编号
calculate_eth_number() {
    eth_num=$(eval echo $(ip a | awk -F'h|:' '/eth[0-9]+:/{print $3}' | tail -n1) + 1 + ${init_num} | bc)
    if [ -z "$eth_num" ]; then
        echo "计算新的 eth 编号失败。"
        exit 1
    fi
}

# 写入 udev 规则文件
write_udev_rule() {
    sed -i "/eth$eth_num/d" "$rule_file"
    cat >> "$rule_file" <<-EOF
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="$mac_num", ATTR{type}=="1", NAME="eth$eth_num"
EOF
    if [ $? -ne 0 ]; then
        echo "写入 udev 规则文件 $rule_file 失败。"
        exit 1
    fi
}

# 移动 NetworkManager 连接配置文件
move_network_config_file() {
    local net_dir='/etc/NetworkManager/system-connections'
    mv "$net_dir/$new_devi"* "$net_dir/eth$eth_num.nmconnection"
    if [ $? -ne 0 ]; then
        echo "移动 NetworkManager 连接配置文件失败。"
        exit 1
    fi
}

# 获取用户输入的 IP 地址并验证格式
get_user_ip_address() {
    while true; do
        read -p "请输入新的 IP 地址（格式如 10.0.0.118）: " new_ipaddr
        if [[ $new_ipaddr =~ ^([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]]; then
            break
        else
            echo "输入的 IP 地址格式不正确，请重新输入。"
        fi
    done
}

# 写入新的 NetworkManager 连接配置文件
write_network_config_file() {
    cat > "$net_dir/eth$eth_num.nmconnection" <<-EOF
[connection]
id=eth$eth_num
type=ethernet
autoconnect-priority=-999
interface-name=eth$eth_num

[ethernet]

[ipv4]
address1=$new_ipaddr/24,10.0.0.2
dns=10.0.0.2;
method=manual
EOF
    if [ $? -ne 0 ]; then
        echo "写入新的 NetworkManager 连接配置文件失败。"
        exit 1
    fi
}

# 清理无效的网卡绑定信息
clean_net_rename_msg(){
    # 获取当前所有有效网卡的 MAC 地址
    current_macs_array=($(ip -o link | awk -F': ' '{print $2}' | while read -r iface; do
                   ip link show "$iface" | awk '/link\/ether/ {print $2}'
                   done))
    
    # 获取绑定的mac地址信息	
    all_macs=$(awk -F'="|",' '{print $6}' "${rule_file}")
    
    # 初始化结果字符串为空
    result=""
    
    # 遍历 all_macs 中的每个元素
    for element in $all_macs; do
        found=false
        # 检查当前元素是否在 current_macs_array 中
        for mac in "${current_macs_array[@]}"; do
            if [ "$element" = "$mac" ]; then
                found=true
                break
            fi
        done
        # 如果当前元素不在 current_macs_array 中，则输出该元素
        if [ "$found" = false ]; then
            result="${result} ${element}"
        fi
    done
    
    # 清理无效的网卡绑定信息
    for i in ${result}; do
        sed -i "/${i}/d" "${rule_file}"
    done
}

# 定制一个网卡的配置
define_network_interface(){
    extract_connection_info
    modify_connection_name
    extract_mac_address
    calculate_eth_number
    write_udev_rule
    move_network_config_file
    get_user_ip_address
    write_network_config_file
}

# 获取所有的新增网卡设备
get_new_device(){
    # 默认情况下，新增加网卡是没有启动的
    device_list=($(nmcli device  | awk '/--/{print $1}'))
    init_num=0
    if [ ${#device_list[@]} -ne 0 ]; then
        for new_devi in ${device_list[@]}; do
            define_network_interface
            let init_num+=1
        done
    fi
}


# 主函数，按顺序调用各个功能函数
main() {
    check_command "nmcli"
    clean_net_device_msg
    get_new_device
    clean_net_rename_msg
    echo "脚本执行成功，新的网络连接已配置为 eth$eth_num。"
    echo "重启主机"
    reboot
}

# 执行主函数
main
